home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 105 (1991-02)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 105 (1991-02)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / AmigaUUCP / uucico / gio.c < prev    next >
C/C++ Source or Header  |  1991-01-16  |  19KB  |  960 lines

  1.  
  2. /*
  3.  *  GIO.C    WINDOWED G PROTOCOL
  4.  *
  5.  *  written from scratch, except the checksum routine which was
  6.  *  rewritten but based on the old one.
  7.  *
  8.  *  WINDOW SIZE:    When changing the window size be sure there
  9.  *            are enough buffers available for pending txs.
  10.  *
  11.  *  GIO.C (c)Copyright 1989, Matthew Dillon, All Rights Reserved
  12.  *  extended to window size of 7 by Jack J. Rouse
  13.  */
  14.  
  15. #include "includes.h"
  16.  
  17.  
  18. typedef unsigned char    ubyte;
  19. typedef unsigned short    uword;
  20.  
  21. typedef struct {
  22.     ubyte   Dle;    /*  Literal ASCII DLE                */
  23.     ubyte   K;        /*  data size 2^(K+4) except K=0 means no data  */
  24.     ubyte   CL,CH;    /*  MAGIC - chksum(data) ^ C        */
  25.     ubyte   C;
  26.     ubyte   X;        /*  K ^ C0 ^ C1 ^ C            */
  27. } Frame;
  28.  
  29. typedef struct {
  30.     ubyte   CType;    /*  bits 7-6 of C    */
  31.     ubyte   CCmd;    /*  bits 5-3 of C    */
  32.     ubyte   CSeq;    /*  bits 2-0 of C    */
  33.     ubyte   PLen;    /*  pre-data (2 bytes) for SHORTDATA type */
  34.     ubyte   *Data;    /*  implies CType=LONGDATA or SHORTDATA */
  35.     uword   DLen;    /*  length of data    */
  36. } Packet;
  37.  
  38. Prototype int gwrdata(FILE *);
  39. Prototype int gwrmsg(char *);
  40. Prototype int grddata(FILE *);
  41. Prototype int grdmsg(char *, int);
  42. Prototype int gturnon(int);
  43. Prototype int gturnoff(void);
  44. Prototype void ResetGIO(void);
  45.  
  46. Prototype short ReducedTimeout;
  47.  
  48. short ReducedTimeout;
  49.  
  50. Local      char *GetTxBuf(void);
  51. Local      int SendDataPacket(unsigned char *, int);
  52. Local      int RecvDataPacket(char **);
  53. Local      int GetData(int, Packet *);
  54. Local      int RecvdAck(char);
  55. Local      int WriteCtlPacket(int);
  56. Local      int WritePacket(Packet *, int);
  57. Local      int ReadPacket(Packet *, int);
  58. Local      int CheckSum(unsigned char *, int);
  59. Local      void FrameToPacket(Frame *, Packet *, unsigned char *);
  60. Local      int LenToK(unsigned short);
  61.  
  62. extern int debug;
  63. extern int WindowSize;
  64.  
  65. #define SUCCESS 0
  66. #define FAIL    1
  67.  
  68. #define MAGIC        0125252
  69. #define DLE        0x10
  70. #define WINDOWSIZE  7
  71. #define SEGSIZEK    2        /*  64 bytes ??     */
  72.  
  73. #define SUB1(var)   (((var)-1)&7)
  74.  
  75.  
  76. #define CT_CONTROL    (0 << 6)
  77. #define CT_ALTCHN    (1 << 6)
  78. #define CT_LONGDATA    (2 << 6)
  79. #define CT_SHORTDATA    (3 << 6)
  80. #define CT_MASK     (3 << 6)
  81.  
  82. #define CC_CLOSE    (1 << 3)
  83. #define CC_RJ        (2 << 3)
  84. #define CC_SRJ        (3 << 3)
  85. #define CC_RR        (4 << 3)
  86. #define CC_INITC    (5 << 3)
  87. #define CC_INITB    (6 << 3)
  88. #define CC_INITA    (7 << 3)
  89. #define CC_MASK     (7 << 3)
  90.  
  91. #define SEQ_MASK    7
  92.  
  93. #define WAIT_ACK    1
  94. #define WAIT_DATA    2
  95. #define WAIT_CONTROL    3
  96.  
  97. #define MaxPktSize    4096
  98.  
  99. char    RxBuf[MaxPktSize+4];
  100. char    *TxBuf[8];
  101.  
  102.                 /*  TRANSMIT STAGE        */
  103. char    TxSeq = 0;        /*  Last send packet        */
  104. char    TxPend= 0;        /*  hasn't been acked yet   */
  105. uword    TxWinSize;        /*  1 or 2 (max 7)          */
  106. uword    TxSegSize;        /*  maximum segment size    */
  107. char    TxSegK;         /*  K for TxSegSize        */
  108. Packet    TxPacket[8];        /*  contents of last packet */
  109.  
  110.                 /*  RECEIVE STAGE        */
  111. char    RxSeq = 0;        /*  Last valid recv pkt     */
  112. char    RxRdy = 0;        /*  Has come in..        */
  113. char    RxRetry = 8;
  114. char    RxNotAcked = 0;     /*  We have yet to ack it   */
  115. Packet    RxPacket;        /*  The packet that has come in */
  116.  
  117. void
  118. ResetGIO()
  119. {
  120.     TxSeq = 0;
  121.     TxPend= 0;
  122.     TxWinSize = 0;
  123.     TxSegSize = 0;
  124.     TxSegK = 0;
  125.     RxSeq = 0;
  126.     RxRdy = 0;
  127.     RxRetry = 8;
  128.     RxNotAcked = 0;
  129. }
  130.  
  131. /*
  132.  *  Get Transmit Buffer.  Note that some space to the left is available
  133.  */
  134.  
  135. Local
  136. char *
  137. GetTxBuf()
  138. {
  139.     static int index = 0;
  140.  
  141.     if (++index > TxWinSize)
  142.     index = 0;
  143.     if (TxBuf[index] == NULL
  144.     &&    (TxBuf[index] = (char *)malloc(MaxPktSize+4)) == NULL)
  145.     {
  146.     printf("Out of memory in GetTxBuf.");
  147.     /* could handle this case better, but it should be rare */
  148.     xexit(1);
  149.     }
  150.     return(TxBuf[index] + 2);
  151. }
  152.  
  153. int
  154. gwrdata(fi)
  155. FILE *fi;
  156. {
  157.     int bytes;
  158.  
  159.     if (debug > 7)
  160.     printf("GWRDATA: ");
  161.  
  162.     for (;;) {
  163.     char *buf = GetTxBuf();
  164.     if ((bytes = fread(buf, 1, TxSegSize, fi)) <= 0)
  165.         break;
  166.     if (SendDataPacket(buf, bytes) != SUCCESS) {
  167.         if (debug > 7)
  168.         printf("GWR Failed\n");
  169.         return(FAIL);
  170.     }
  171.     if (debug > 7)
  172.         printf("\nGWROK ");
  173.     }
  174.     {
  175.     char *buf = GetTxBuf();
  176.     if (SendDataPacket(buf, 0) != SUCCESS) {
  177.         if (debug > 7)
  178.         printf("GWR Failed (last)\n");
  179.         return(FAIL);
  180.     }
  181.     }
  182.     if (debug > 7)
  183.     printf("\nGWFile Last Ack\n");
  184.     while (TxPend) {
  185.     if (GetData(WAIT_ACK, NULL) == FAIL)
  186.         return(FAIL);
  187.     }
  188.     if (debug > 7)
  189.     printf("success\n");
  190.     return (SUCCESS);
  191. }
  192.  
  193. /*
  194.  *  Write message to the other guy.
  195.  *
  196.  *  NOTE: LONGDATA packets used exclusively and \0 fill to end.
  197.  */
  198.  
  199. int
  200. gwrmsg(str)
  201. char *str;
  202. {
  203.     int len = strlen(str) + 1;      /*  type + str + \0  */
  204.  
  205.     if (debug > 7)
  206.     printf("GWRMSG: %s\n", str);
  207.  
  208.     while (len > TxSegSize) {
  209.     char *buf = GetTxBuf();
  210.     movmem(str, buf, TxSegSize);
  211.     if (debug > 7)
  212.         printf("GWR-SEND %d\n", TxSegSize);
  213.     if (SendDataPacket(buf, TxSegSize) != SUCCESS)
  214.         return(FAIL);
  215.     len -= TxSegSize;
  216.     str += TxSegSize;
  217.     }
  218.  
  219.     /*
  220.      *    Find optimal packet size (remember, we must force LONGDATA
  221.      *
  222.      *    Apparently packet sizes less than the agreed upon size are
  223.      *    not allowed ???
  224.      */
  225.  
  226.     {
  227.     short siz = TxSegSize;
  228.     char *buf = GetTxBuf();
  229. #ifdef NOTDEF
  230.     short k = TxSegK;
  231.  
  232.     while (k > 1 && (siz >> 1) >= len) {
  233.         --k;
  234.         siz >>= 1;
  235.     }
  236. #endif
  237.     if (debug > 7)
  238.         printf("GWR-FNL %d %d\n", len, siz);
  239.  
  240.     movmem(str, buf, len);
  241.     setmem(buf + len, siz - len, 0);
  242.     if (SendDataPacket(buf, siz) != SUCCESS) {
  243.         if (debug > 7)
  244.         printf("GWR-FAIL\n");
  245.         return(FAIL);
  246.     }
  247.     }
  248.     if (debug > 7)
  249.     printf("GWR Last Ack\n");
  250.     while (TxPend) {
  251.     if (GetData(WAIT_ACK, NULL) == FAIL)
  252.         return(FAIL);
  253.     }
  254.     if (debug > 7)
  255.     printf("success\n");
  256.     return (SUCCESS);
  257. }
  258.  
  259. int
  260. grddata(fi)
  261. FILE *fi;
  262. {
  263.     int bytes;
  264.     char *buf;
  265.  
  266.     if (debug > 7)
  267.     printf("GRDDATA\n");
  268.     while ((bytes = RecvDataPacket(&buf)) > 0) {
  269.     if (debug > 7)
  270.         printf("GRDDATA blk %d\n", bytes);
  271.     fwrite(buf, 1, bytes, fi);
  272.     }
  273.     if (debug > 7)
  274.     printf("GRDDATA end %d\n", bytes);
  275.     if (bytes < 0)
  276.     return(FAIL);
  277.     else
  278.     return(SUCCESS);
  279. }
  280.  
  281. int
  282. grdmsg(buf, maxlen)
  283. char *buf;
  284. {
  285.     short i;
  286.     short n;
  287.     short slen;
  288.     char *ptr;
  289.  
  290.     i = 0;
  291.     if (debug > 7)
  292.     printf("GRDMSG\n");
  293.     while ((n = RecvDataPacket(&ptr)) > 0) {
  294.     ptr[n] = 0;
  295.     slen = strlen(ptr);
  296.     if (slen > maxlen - 1) {
  297.         printf("GRDMSG: Buffer overflow!\n");
  298.         return (FAIL);
  299.     }
  300.     movmem(ptr, buf + i, slen);
  301.     buf[i + slen] = 0;
  302.     if (slen != n)
  303.         break;
  304.     i += slen;
  305.     maxlen -= slen;
  306.     }
  307.     if (debug > 7)
  308.     printf("GRDMSGEND %d (%d) %s\n", n, i, buf);
  309.     if (n < 0) {
  310.     buf[0] = 0;
  311.     return(FAIL);
  312.     }
  313.     return(SUCCESS);
  314. }
  315.  
  316. Local
  317. int
  318. SendDataPacket(buf, bytes)
  319. ubyte *buf;
  320. int bytes;
  321. {
  322.     Packet  P;
  323.  
  324.     /*
  325.      *    If window exhausted we must wait for at least one ack.
  326.      */
  327.  
  328.     while (TxPend == TxWinSize) {
  329.     if (GetData(WAIT_ACK, NULL) == FAIL)
  330.         return(FAIL);
  331.     }
  332.  
  333.     TxSeq = (TxSeq + 1) & 7;        /*  next Tx packet  */
  334.  
  335.     /*
  336.      *    Figure out best fit packet size.  Apparently packets smaller
  337.      *    then the agreed upon size are not allowed ???
  338.      */
  339.  
  340. #ifdef NOTDEF
  341.     {
  342.     short k = TxSegK;
  343.     P.DLen = TxSegSize;
  344.     while (k > 1 && P.DLen && (P.DLen >> 1) >= bytes) {
  345.         --k;
  346.         P.DLen >>= 1;
  347.     }
  348.     }
  349. #else
  350.     P.DLen = TxSegSize;
  351. #endif
  352.  
  353.     if (bytes < P.DLen) {
  354.     uword extra = P.DLen - bytes;
  355.     setmem(buf + bytes, extra, 0);
  356.     if (extra <= 127) {
  357.         P.PLen = 1;
  358.         buf[-1] = extra;
  359.     } else {
  360.         P.PLen = 2;
  361.         buf[-2] = 0x80 | extra;
  362.         buf[-1] = (extra >> 7);
  363.     }
  364.     P.CType = CT_SHORTDATA;
  365.     } else {
  366.     P.PLen = 0;
  367.     P.CType = CT_LONGDATA;
  368.     }
  369.     P.CCmd = TxSeq << 3;    /*  transmit sequence number */
  370.     P.CSeq = RxSeq;        /*  last valid received pkt  */
  371.     P.Data = buf;
  372.  
  373.     if (debug > 7)
  374.     printf("WRITE DATA PACKET txseq=%d rxack=%d\n", TxSeq, P.CSeq);
  375.  
  376. #ifdef NOTDEF
  377.     RxNotAcked = 0;        /*  We've acked the rx packet */
  378. #else
  379.     if (RxNotAcked) {           /*  always send CC_RR packets */
  380.     WriteCtlPacket(CC_RR | RxSeq);
  381.     RxNotAcked = 0;
  382.     }
  383. #endif
  384.  
  385.     TxPacket[TxSeq] = P;
  386.     ++TxPend;
  387.  
  388.     WritePacket(&TxPacket[TxSeq], 1);
  389.  
  390.     return(SUCCESS);
  391. }
  392.  
  393. Local
  394. int
  395. RecvDataPacket(pbuf)
  396. char **pbuf;
  397. {
  398.     if (RxRdy == 0) {
  399.     if (GetData(WAIT_DATA, NULL) != SUCCESS)
  400.         return(-1);
  401.     }
  402.     *pbuf = RxPacket.Data;
  403.     RxRdy = 0;
  404.     return((int)RxPacket.DLen);
  405. }
  406.  
  407. int
  408. gturnon(master)
  409. int master;
  410. {
  411.     Packet P;
  412.     short retry = 5;
  413.     short windowsize = WINDOWSIZE;    /*  our prefered window size    */
  414.     short segsize = SEGSIZEK;        /*  our prefered segment size    */
  415.  
  416.     if (WindowSize < windowsize)        /*  command line override       */
  417.     windowsize = WindowSize;
  418.  
  419.     if (master) {
  420.     while (retry > 0) {
  421.         WriteCtlPacket(CC_INITA | windowsize);
  422.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
  423.         if (P.CSeq && P.CSeq < windowsize)
  424.             windowsize = P.CSeq;
  425.         break;
  426.         }
  427.         --retry;
  428.     }
  429.     while (retry > 0) {
  430.         WriteCtlPacket(CC_INITB | (segsize - 1));
  431.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
  432.         if (P.CSeq < segsize - 1)
  433.             segsize = P.CSeq + 1;
  434.         break;
  435.         }
  436.         --retry;
  437.     }
  438.     while (retry > 0) {
  439.         WriteCtlPacket(CC_INITC | windowsize);
  440.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
  441.         if (P.CSeq && P.CSeq < windowsize)
  442.             windowsize = P.CSeq;
  443.         break;
  444.         }
  445.         --retry;
  446.     }
  447.     } else {
  448.     while (retry > 0) {
  449.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
  450.         WriteCtlPacket(CC_INITA | windowsize);
  451.         if (P.CSeq && windowsize > P.CSeq)
  452.             windowsize = P.CSeq;
  453.         break;
  454.         }
  455.         --retry;
  456.     }
  457.     while (retry > 0) {
  458.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
  459.         WriteCtlPacket(CC_INITB | (segsize - 1));
  460.         if (P.CSeq < segsize - 1)
  461.             segsize = P.CSeq + 1;
  462.         break;
  463.         }
  464.         --retry;
  465.     }
  466.     while (retry > 0) {
  467.         if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
  468.         WriteCtlPacket(CC_INITC | windowsize);
  469.         if (P.CSeq && windowsize > P.CSeq)
  470.             windowsize = P.CSeq;
  471.         break;
  472.         }
  473.         --retry;
  474.     }
  475.     }
  476.     TxSegK = segsize;
  477.     TxSegSize = 1 << (TxSegK + 4);
  478.     TxWinSize = windowsize;
  479.     if (debug > 0)
  480.     printf("Window Size is %d\n", TxWinSize);
  481.     if (retry == 0)
  482.     return(FAIL);
  483.     return(SUCCESS);
  484. }
  485.  
  486. int
  487. gturnoff()
  488. {
  489.     Packet P;
  490.  
  491.     WriteCtlPacket(CC_CLOSE);
  492.     if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_CLOSE) {
  493.     WriteCtlPacket(CC_RR | RxSeq);
  494.     return (SUCCESS);
  495.     }
  496.     return (FAIL);
  497. }
  498.  
  499. /*
  500.  *  GetData()
  501.  *
  502.  *  This is the core of the packet protocol.  As soon as we get a satisfactory
  503.  *  terminating condition we return.  However, on unsatisfactory conditions
  504.  *  such as having to send a reject, we attempt to drain any pending data
  505.  *  (i.e. multiple returned rejects) so we do not do multiple resends.
  506.  *
  507.  *  The resend flag only applies on a failure return.
  508.  */
  509.  
  510. Local
  511. int
  512. GetData(waitfor, p)
  513. int waitfor;
  514. Packet *p;
  515. {
  516.     Packet P;
  517.     short timeout;
  518.     short drainmode = 0;
  519.  
  520.     /*
  521.      *    If we haven't acked the last packet we received we must do
  522.      *    so now before we can expect to receive another one!
  523.      */
  524.  
  525.     if (debug > 7)
  526.     printf("Get-Data waitfor %s\n", (waitfor == WAIT_ACK) ? "WAIT_ACK" : "WAIT_DATA");
  527.     if (waitfor == WAIT_ACK)
  528.     timeout = (PacketTimeout) ? PacketTimeout : 5;
  529.     else if (waitfor == WAIT_DATA)
  530.     timeout = (PacketTimeout) ? PacketTimeout * 4 : 20;
  531.     else
  532.     timeout = (PacketTimeout) ? PacketTimeout * 4 : 20;
  533.  
  534.     for (;;) {
  535.     /*
  536.      *  due to confusion on connection termination, we do not wait
  537.      *  around trying to retry the final termination acknowlege.
  538.      */
  539.  
  540.     if (ReducedTimeout) {
  541.         if (RxRetry > 2)
  542.         RxRetry = 2;
  543.         if (timeout > 5)
  544.         timeout = 5;
  545.     }
  546.     if (RxNotAcked) {                   /*  good, send ack for rx'd pkt */
  547.         WriteCtlPacket(CC_RR | RxSeq);
  548.         RxNotAcked = 0;
  549.     }                    /*    bad, timeout on read        */
  550.     if (ReadPacket(&P, (drainmode) ? 0 : timeout) == FAIL) {
  551.         drainmode = 0;
  552.  
  553.         /*
  554.          *    If we have timed out waiting for data then send a reject
  555.          */
  556.  
  557.         if (waitfor == WAIT_DATA) {
  558.         if (RxRetry) {
  559.             --RxRetry;
  560.             if (debug > 7)
  561.             printf("\nWAIT-DATA, TIMEOUT, SEND RJ\n");
  562.             WriteCtlPacket(CC_RJ | RxSeq);
  563.             continue;
  564.         }
  565.         }
  566.  
  567.         /*
  568.          *    If we have timed out waiting for an ack send the entire
  569.          *    window.  We must send the window sometime and it might as
  570.          *    well be now.
  571.          */
  572.  
  573.         if (waitfor == WAIT_ACK) {
  574.         if (RxRetry) {
  575.             int i;
  576.  
  577.             if (debug > 7)
  578.             printf("RESEND %d packets\n", TxPend);
  579.             for (i = 1; i <= TxPend; ++i) {
  580.             Packet *p = &TxPacket[(TxSeq - TxPend + i) & 7];
  581.             p->CSeq = RxSeq;
  582.             WritePacket(p, 1);
  583.             }
  584.             --RxRetry;
  585.             continue;
  586.         }
  587.         }
  588.         if (debug > 7)
  589.         printf("COMPLETE FAILURE RxRetry = %d\n", RxRetry);
  590.         return(FAIL);
  591.     }
  592.  
  593.     /*
  594.      *  valid packet, terminating condition?
  595.      */
  596.  
  597.     RxRetry = 8;
  598.     switch(P.CType) {
  599.     case CT_CONTROL:
  600.         switch(P.CCmd) {
  601.         case CC_CLOSE:  /*    End of communication ... not an ACK!       */
  602.         if (waitfor == WAIT_CONTROL) {
  603.             *p = P;
  604.             return(SUCCESS);
  605.         }
  606.         return(FAIL);
  607.         case CC_RJ:     /*    Reject packet (P.CSeq == last good packet) */
  608.         (void)RecvdAck(P.CSeq);
  609.         drainmode = 1;
  610.         break;
  611.         case CC_SRJ:    /*    Selective Reject (P.CSeq == bad packet # ) */
  612.         return(FAIL);
  613.         case CC_RR:     /*    Ack to packet  (P.CSeq == packet # acked)   */
  614. #ifdef NOTDEF
  615.         if (P.CSeq == ((TxSeq - TxPend) & 7)) {
  616.             /*
  617.              * The CSeq packet was previously acknowledged
  618.              * The receiver apparently has not seen anything since.
  619.              * This is the same as a rejection.
  620.              */
  621.             goto resend;
  622.         }
  623. #endif
  624.         if (RecvdAck(P.CSeq) == SUCCESS && waitfor == WAIT_ACK)
  625.             return(SUCCESS);
  626.         break;
  627.         case CC_INITC:
  628.         case CC_INITB:
  629.         case CC_INITA:
  630.         if (waitfor == WAIT_CONTROL) {
  631.             *p = P;
  632.             return(SUCCESS);
  633.         }
  634.         return(FAIL);
  635.         }
  636.         break;
  637.     case CT_ALTCHN:
  638.         printf("ALTCHN packet ??\n");
  639.         break;
  640.     case CT_LONGDATA:
  641.     case CT_SHORTDATA:
  642.         {
  643.         char rxseq = P.CCmd >> 3;
  644.         char txack = P.CSeq;
  645.  
  646.         if (RxRdy == 1) {
  647.             printf("Got two receive packets without me acking!\n");
  648.         }
  649.  
  650.         if (rxseq == RxSeq) {   /*  already got this packet */
  651.             RxNotAcked = 1;
  652.             continue;
  653.                     /*  expected packet?        */
  654.         } else if (rxseq != ((RxSeq + 1) & 7)) {
  655.             drainmode = 1;
  656.             printf("Received sequence %d, expected %d\n", rxseq, (RxSeq + 1) & 7);
  657.             break;
  658.         }
  659.         if (debug > 6)
  660.             printf("RECV SEQUENCE %d\n", rxseq);
  661.  
  662.         RecvdAck(txack);    /*  woa */
  663.  
  664.         /*
  665.          *  Delay sending the ACK back in case we can combine
  666.          *  it with the next transmitted packet.
  667.          */
  668.  
  669.         RxNotAcked = 1;     /*  we haven't ack'd the rx packet */
  670.  
  671.         RxSeq = (RxSeq + 1) & 7;
  672.         RxRdy = 1;
  673.         RxPacket = P;
  674.         if (waitfor == WAIT_DATA)
  675.             return(SUCCESS);
  676.         if (TxPend == 0 && waitfor == WAIT_ACK)
  677.             return(SUCCESS);
  678.         }
  679.         break;
  680.     }
  681.     }
  682. }
  683.  
  684. Local
  685. int
  686. RecvdAck(seq)
  687. char seq;
  688. {
  689.     short i;
  690.  
  691.     /*
  692.      *    which packet was acked?
  693.      */
  694.  
  695.     for (i = 0; i < TxPend; ++i) {
  696.     if (seq == ((TxSeq - i) & 7))
  697.         break;
  698.     }
  699.     if (i && i == TxPend) {
  700.     if (seq != ((TxSeq - TxPend) & 7))
  701.         printf("He acked the wrong packet! %d expected %d\n", seq, TxSeq);
  702.     return(FAIL);
  703.     }
  704.     if (debug > 7)
  705.     printf("TxPend %d -> %d\n", TxPend, i);
  706.     TxPend = i;
  707.     return(SUCCESS);
  708. }
  709.  
  710. Local
  711. int
  712. WriteCtlPacket(cc)
  713. int cc;
  714. {
  715.     Packet pk;
  716.  
  717.     pk.CType = CT_CONTROL;
  718.     pk.CCmd  = cc & CC_MASK;
  719.     pk.CSeq  = cc & SEQ_MASK;
  720.     pk.PLen  = 0;
  721.     pk.DLen  = 0;
  722.     WritePacket(&pk, 0);
  723.     return(SUCCESS);
  724. }
  725.  
  726. Local
  727. int
  728. WritePacket(pk, async)
  729. Packet *pk;
  730. int async;
  731. {
  732.     Frame   F;
  733.     uword   sum;
  734.  
  735.     F.Dle = DLE;
  736.     F.C   = pk->CType | pk->CCmd | pk->CSeq;
  737.     F.K   = 9;
  738.  
  739.     if (pk->CType == CT_SHORTDATA || pk->CType == CT_LONGDATA)
  740.     F.K = LenToK(pk->DLen);
  741.     else
  742.     pk->DLen = 0;
  743.  
  744.     sum = MAGIC - (CheckSum(pk->Data - pk->PLen, pk->DLen) ^ F.C);
  745.  
  746.     F.CH  = sum >> 8;
  747.     F.CL  = sum;
  748.     F.X   = F.K ^ F.CH ^ F.CL ^ F.C;
  749.  
  750.     if (debug > 7)
  751.     printf("WritePacket: F.K = %d F.C = %d.%d.%d\n", F.K, F.C >> 6, (F.C >> 3) & 7, F.C & 7);
  752.  
  753.     if (async)
  754.     xwritea(&F, sizeof(F));
  755.     else
  756.     xwrite(&F, sizeof(F));      /*  write header    */
  757.     if (pk->DLen) {             /*  write data      */
  758.     if (async)
  759.         xwritea(pk->Data - pk->PLen, pk->DLen);
  760.     else
  761.         xwrite(pk->Data - pk->PLen, pk->DLen);
  762.     }
  763.     return(SUCCESS);
  764. }
  765.  
  766. Local
  767. int
  768. ReadPacket(pk, timeout)
  769. Packet *pk;
  770. int timeout;
  771. {
  772.     Frame   F;
  773.     short   c;
  774.     short   i = 0;
  775.  
  776.     pk->Data = RxBuf;
  777.     pk->CType = 0xFF;
  778.     pk->CCmd  = 0;
  779.     pk->CSeq  = 0;
  780.  
  781.     if (debug > 7)
  782.     printf("ReadPacket\n");
  783.     while ((c = xgetc(timeout)) != EOF) {
  784.     if (debug > 8)
  785.         printf("RP %d %02x\n", i, c);
  786.  
  787.     switch(i) {
  788.     case 0:
  789.         if (c == DLE) {
  790.         F.Dle = c;
  791.         ++i;
  792.         if (timeout == 0)
  793.             timeout = 1;
  794.         }
  795.         break;
  796.     case 1:
  797.         F.K = c;
  798.         ++i;
  799.         if (c == DLE) { /*  K only valid 1-9    */
  800.         F.Dle = c;
  801.         i = 1;
  802.         }
  803.         else if (c == 0 || c > 9)
  804.         i = 0;
  805.         break;
  806.     case 2:
  807.         F.CL = c;
  808.         ++i;
  809.         break;
  810.     case 3:
  811.         F.CH = c;
  812.         ++i;
  813.         break;
  814.     case 4:
  815.         F.C = c;
  816.         ++i;
  817.         break;
  818.     case 5:
  819.         F.X = c;
  820.         if (F.X != (F.K ^ F.CH ^ F.CL ^ F.C)) {
  821.         printf("F.X failed: %02x %02x\n", F.X, (F.K ^ F.CH ^ F.CL ^ F.C));
  822.         i = 0;
  823.         } else {        /*    get data segment if any */
  824.         ++i;
  825.         }
  826.         break;
  827.     }
  828.     if (i == 6)
  829.         break;
  830.     }
  831.     if (debug > 7) {
  832.     if (i)
  833.         printf("RP Hdr i = %d, F.K = %d F.C = %d.%d.%d\n", i, F.K, F.C >> 6, (F.C >> 3) & 7, F.C & 7);
  834.     else
  835.         printf("RP Hdr <rx timeout>\n");
  836.     }
  837.  
  838.     if (i == 6) {       /*  Receive Data Portion    */
  839.     uword pktsize = 1 << (F.K + 4);
  840.     uword n;
  841.  
  842.     if (F.K == 9)
  843.         pktsize = 0;
  844.  
  845.     if (pktsize > MaxPktSize) {
  846.         printf("Protocol failure pktsize %d/%d/%d\n", pktsize, TxSegSize, MaxPktSize);
  847.         return (FAIL);
  848.     }
  849.     for (n = 0; n < pktsize; ++n) {
  850.         if ((c = xgetc(4)) == EOF)
  851.         break;
  852.         pk->Data[n] = c;
  853.     }
  854.     if (c != EOF) {
  855.         uword hissum;
  856.         uword oursum;
  857.         hissum = (F.CH << 8) | F.CL;
  858.         oursum = MAGIC - (CheckSum(pk->Data, pktsize) ^ F.C);
  859.         if (debug > 7)
  860.         printf("Got Data, checking: %04x %04x\n", hissum, oursum);
  861.         if (hissum == oursum) {
  862.         FrameToPacket(&F, pk, pk->Data);
  863.         return (SUCCESS);
  864.         }
  865.     } else {
  866.         FrameToPacket(&F, pk, pk->Data);    /* mainly for pk->CType */
  867.         return (FAIL);
  868.     }
  869.     }
  870.     /*
  871.      *    Timeout, retry?
  872.      */
  873.     return (FAIL);
  874. }
  875.  
  876. Local
  877. int
  878. CheckSum(s, n)
  879. ubyte *s;
  880. int n;
  881. {
  882.     uword sum;
  883.     uword x;
  884.     uword t;
  885.  
  886.     if (n == 0)
  887.     return(0);
  888.     sum = -1;
  889.     x = 0;
  890.  
  891.     while (n) {
  892.     if (sum & 0x8000)
  893.         sum = (sum << 1) | 1;
  894.     else
  895.         sum = (sum << 1);
  896.  
  897.     t = sum;
  898.     sum += *s++;
  899.     x += sum ^ n;
  900.     if (sum <= t)
  901.         sum ^= x;
  902.     --n;
  903.     }
  904.     return((int)sum);
  905. }
  906.  
  907. Local
  908. void
  909. FrameToPacket(fr, pk, data)
  910. Frame *fr;
  911. Packet *pk;
  912. ubyte *data;
  913. {
  914.     pk->CType = fr->C & CT_MASK;
  915.     pk->CCmd  = fr->C & CC_MASK;
  916.     pk->CSeq  = fr->C & SEQ_MASK;
  917.     switch(pk->CType) {
  918.     case CT_LONGDATA:
  919.     pk->DLen = 1 << (fr->K + 4);
  920.     break;
  921.     case CT_SHORTDATA:
  922.     pk->DLen = 1 << (fr->K + 4);
  923.     if (pk->Data[0] & 0x80) {
  924.         pk->DLen -= (pk->Data[0] & 0x7F) | (pk->Data[1] << 7);
  925.         if (pk->DLen < 0) {
  926.         printf("DLEN ERROR %d\n", pk->DLen);
  927.         pk->DLen = 0;
  928.         }
  929.         pk->Data += 2;
  930.     } else {
  931.         pk->DLen -= *pk->Data;
  932.         ++pk->Data;
  933.     }
  934.     break;
  935.     default:
  936.     pk->DLen = 0;
  937.     break;
  938.     }
  939. }
  940.  
  941. Local
  942. int
  943. LenToK(bytes)
  944. uword bytes;
  945. {
  946.     uword n = 32;
  947.     uword k = 1;
  948.  
  949.     while (n < bytes) {
  950.     n <<= 1;
  951.     ++k;
  952.     }
  953.     if (k > 8) {
  954.     printf("Soft error, LenToK: %d %d %d\n", bytes, n, k);
  955.     k = 8;
  956.     }
  957.     return((int)k);
  958. }
  959.  
  960.